package org.jboss.resteasy.test.providers.multipart.resource;


import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import org.jboss.resteasy.annotations.providers.multipart.XopWithMultipartRelated;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartRelatedInput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartRelatedOutput;

@Path("")
public class ContextProvidersResource {

   private static Logger logger = Logger.getLogger(ContextProvidersResource.class);

   @GET
   @Produces("multipart/mixed")
   @Path("get/mixed")
   public MultipartOutput getMixed() {
      logger.info("entering getMixed()");
      MultipartOutput output = new MultipartOutput();
      output.addPart(new ContextProvidersCustomer("Bill"), MediaType.APPLICATION_XML_TYPE);
      output.addPart("Bob", MediaType.TEXT_PLAIN_TYPE);
      return output;
   }

   @GET
   @Produces("multipart/form-data")
   @MultipartForm
   @Path("get/form")
   public MultipartFormDataOutput getForm() {
      logger.info("entering getForm()");
      MultipartFormDataOutput output = new MultipartFormDataOutput();
      output.addFormData("bill", new ContextProvidersCustomer("Bill"), MediaType.APPLICATION_XML_TYPE, "tmp1");
      output.addFormData("bob", "Bob", MediaType.TEXT_PLAIN_TYPE);
      return output;
   }

   @GET
   @Produces("multipart/mixed")
   @PartType("application/xml")
   @Path("get/list")
   public List<ContextProvidersCustomer> getList() {
      logger.info("entering getList()");
      List<ContextProvidersCustomer> list = new ArrayList<ContextProvidersCustomer>();
      list.add(new ContextProvidersCustomer("Bill"));
      list.add(new ContextProvidersCustomer("Bob"));
      return list;
   }

   @GET
   @Produces("multipart/form-data")
   @PartType("application/xml")
   @Path("get/map")
   public Map<String, ContextProvidersCustomer> getMap() {
      logger.info("entering getMap()");
      Map<String, ContextProvidersCustomer> map = new HashMap<String, ContextProvidersCustomer>();
      map.put("bill", new ContextProvidersCustomer("Bill"));
      map.put("bob", new ContextProvidersCustomer("Bob"));
      return map;
   }

   @GET
   @Produces("multipart/related")
   @Path("get/related")
   public MultipartRelatedOutput getRelated() {
      logger.info("entering getRelated()");
      MultipartRelatedOutput output = new MultipartRelatedOutput();
      output.setStartInfo("text/html");
      output.addPart("Bill", new MediaType("image", "png"), "bill", "binary");
      output.addPart("Bob", new MediaType("image", "png"), "bob", "binary");
      return output;
   }

   @GET
   @Path("get/multipartform")
   @Produces("multipart/form-data")
   @MultipartForm
   public ContextProvidersCustomerForm getMultipartForm() {
      ContextProvidersCustomerForm form = new ContextProvidersCustomerForm();
      form.setCustomer(new ContextProvidersCustomer("Bill"));
      return form;
   }

   @GET
   @Path("get/multipartform2")
   @Produces("multipart/form-data")
   @MultipartForm
   public ContextProvidersCustomerFormNewAnnotationOnField getMultipartForm2() {
      ContextProvidersCustomerFormNewAnnotationOnField form = new ContextProvidersCustomerFormNewAnnotationOnField();
      form.setCustomer(new ContextProvidersCustomer("Bill"));
      return form;
   }

   @GET
   @Path("get/multipartform3")
   @Produces("multipart/form-data")
   @MultipartForm
   public ContextProvidersCustomerFormNewAnnotationOnSetter getMultipartForm3() {
      ContextProvidersCustomerFormNewAnnotationOnSetter form = new ContextProvidersCustomerFormNewAnnotationOnSetter();
      form.setCustomer(new ContextProvidersCustomer("Bill"));
      return form;
   }

   @GET
   @Path("get/xop")
   @Produces("multipart/related")
   @XopWithMultipartRelated
   public ContextProvidersXop getXop() {
      return new ContextProvidersXop("goodbye world".getBytes());
   }

   @POST
   @Consumes("multipart/mixed")
   @Produces(MediaType.APPLICATION_XML)
   @Path("post/mixed")
   public List<ContextProvidersName> postMixed(MultipartInput input) throws IOException {
      logger.info("entering getMixed()");
      List<InputPart> list = input.getParts();
      List<ContextProvidersName> names = new ArrayList<ContextProvidersName>();
      for (Iterator<InputPart> it = list.iterator(); it.hasNext(); ) {
         InputPart inputPart = it.next();
         if (MediaType.APPLICATION_XML_TYPE.equals(inputPart.getMediaType())) {
            names.add(new ContextProvidersName(inputPart.getBody(ContextProvidersCustomer.class, null).getName()));
         } else {
            names.add(new ContextProvidersName(inputPart.getBody(String.class, null)));
         }
      }
      return names;
   }

   @POST
   @Consumes("multipart/form-data")
   @Produces(MediaType.APPLICATION_XML)
   @Path("post/form")
   public List<ContextProvidersName> postForm(MultipartFormDataInput input) throws IOException {
      logger.info("entering postForm()");
      Map<String, List<InputPart>> map = input.getFormDataMap();
      List<ContextProvidersName> names = new ArrayList<ContextProvidersName>();
      for (Iterator<String> it = map.keySet().iterator(); it.hasNext(); ) {
         String key = it.next();
         InputPart inputPart = map.get(key).iterator().next();
         if (MediaType.APPLICATION_XML_TYPE.equals(inputPart.getMediaType())) {
            names.add(new ContextProvidersName(inputPart.getBody(ContextProvidersCustomer.class, null).getName()));
         } else {
            names.add(new ContextProvidersName(inputPart.getBody(String.class, null)));
         }
      }
      return names;
   }

   @POST
   @Consumes("multipart/mixed")
   @Produces(MediaType.APPLICATION_XML)
   @Path("post/list")
   public List<ContextProvidersName> postList(List<ContextProvidersCustomer> customers) throws IOException {
      logger.info("entering postList()");
      List<ContextProvidersName> names = new ArrayList<ContextProvidersName>();
      for (ContextProvidersCustomer customer : customers) {
         names.add(new ContextProvidersName(customer.getName()));
      }
      return names;
   }

   @POST
   @Consumes("multipart/form-data")
   @Produces(MediaType.APPLICATION_XML)
   @Path("post/map")
   public List<ContextProvidersName> postMap(Map<String, ContextProvidersCustomer> customers) throws IOException {
      logger.info("entering postMap()");
      List<ContextProvidersName> names = new ArrayList<ContextProvidersName>();
      for (Iterator<String> it = customers.keySet().iterator(); it.hasNext(); ) {
         String key = it.next();
         ContextProvidersCustomer customer = customers.get(key);
         names.add(new ContextProvidersName(key + ":" + customer.getName()));
      }
      return names;
   }

   @POST
   @Consumes("multipart/related")
   @Produces(MediaType.APPLICATION_XML)
   @Path("post/related")
   public List<ContextProvidersName> postRelated(MultipartRelatedInput customers) throws IOException {
      logger.info("entering postMap()");
      List<ContextProvidersName> names = new ArrayList<ContextProvidersName>();
      for (Iterator<InputPart> it = customers.getParts().iterator(); it.hasNext(); ) {
         InputPart part = it.next();
         String name = part.getBody(String.class, null);
         names.add(new ContextProvidersName(name));
      }
      return names;
   }

   @POST
   @Consumes("multipart/form-data")
   @Path("post/multipartform")
   public String postMultipartForm(@MultipartForm ContextProvidersCustomerForm form) throws IOException {
      logger.info("entering postMultipartForm()");
      return form.getCustomer().getName();
   }

   @POST
   @Consumes("multipart/form-data")
   @Path("post/multipartform2")
   public String postMultipartForm2(@MultipartForm ContextProvidersCustomerFormNewAnnotationOnField form) throws IOException {
      logger.info("entering postMultipartForm()");
      return form.getCustomer().getName();
   }

   @POST
   @Consumes("multipart/form-data")
   @Path("post/multipartform3")
   public String postMultipartForm3(@MultipartForm ContextProvidersCustomerFormNewAnnotationOnSetter form) throws IOException {
      logger.info("entering postMultipartForm()");
      return form.getCustomer().getName();
   }

   @POST
   @Path("post/xop")
   @Consumes("multipart/related")
   public String postXop(@XopWithMultipartRelated ContextProvidersXop xop) {
      return new String(xop.getBytes());
   }
}
